// 重写数组中的部分方法

import { observe } from "./index";

// 获取原数组的原型
const oldArrayProto = Array.prototype;

// 拷贝一份新的数组原型 newArrayProto.__proto__ = oldArrayProto
// 需要保留数组原有的特性，并且重写部分方法
export const newArrayProto = Object.create(oldArrayProto);

// 需要重写的变异方法
const methods = [
    "push",
    "pop",
    "shift",
    "unshift",
    "reverse",
    "sort",
    "splice",
]

methods.forEach(method => {
    newArrayProto[method] = function (...args) {
        // 函数劫持，内部调用原数组的方法，将 this 指向调用者并传入参数
        const result = oldArrayProto[method].call(this, ...args);
        
        // 获取新增的数据
        let inserted;
        // 这里的 this 指向调用者即 data，获取 data 上的 Observer 实例
        let ob = this.__ob__;
        // 只有 push、unshift、splice 方法可以新增操作，其他方法都是修改操作
        switch (method) {
            case "push":
            case "unshift":
                inserted = args;
                break;
            case "splice":
                inserted = args.slice(2);
                break;
        }
        // 判断是否有新增的数据
        if (inserted) {
            // 对新增的数据进行劫持
            ob.observeArray(inserted);
        }
        
        // 数组更新了 dep 通知对应的 watcher 更新数据
        ob.dep.notify();

        return result;
    }
})